import { NameSpace } from 'utils/index';
import exceed from 'utils/apimap';
import { Message } from '@teamix/ui';
import { navigate } from 'utils/router';
import { getProjectInfo } from 'pages/index/pages/project/actions';
import utils from 'utils';
import treeFromPaths from 'components/diffTree/path-to-tree';
import { getProjectServices } from 'api';
import intl from '../../../../../../../locale';

const ns = NameSpace('projectFiles');

export const RECEIVE_STATISTIC = ns('RECEIVE_STATISTIC');

export const CHANGE_ROUTER = ns('CHANGE_ROUTER');
export const RECEIVE_BLOB = ns('RECEIVE_BLOB');
export const RECEIVE_RENDERTYPE = ns('RECEIVE_RENDERTYPE');
export const RECEIVE_LASTCOMMIT = ns('RECEIVE_LASTCOMMIT');
export const RECEIVE_PATHLASTCOMMIT = ns('RECEIVE_PATHLASTCOMMIT');
export const RECEIVE_PATHLASTCOMMIT_BATCH = ns('RECEIVE_PATHLASTCOMMIT_BATCH');
export const RECEIVE_LASTCOMMIT_USER = ns('RECEIVE_LASTCOMMIT_USER');
export const RECEIVE_TREEDATA = ns('RECEIVE_TREEDATA');
export const RECEIVE_CURRENTTREEDATA = ns('RECEIVE_CURRENTTREEDATA');
export const RECEIVE_DEFAULTEXPANDEDKEYS = ns('RECEIVE_DEFAULTEXPANDEDKEYS');
export const RECEIVE_SELECTEDKEYS = ns('RECEIVE_SELECTEDKEYS');
export const ADD_SNIPPET = ns('ADD_SNIPPET');
export const CLEAR_SNIPPET = ns('CLEAR_SNIPPET');
export const RECEIVE_SUBMODULES = ns('RECEIVE_SUBMODULES');
export const RECEIVE_JUMP_LINE_CODE = ns('RECEIVE_JUMP_LINE_CODE');
export const UPDATE_PAGE_INFO = ns('UPDATE_PAGE_INFO');
export const UPDATE_DATA = ns('UPDATE_DATA');
export const RECEIVE_PROTECTED_BRANCHES = ns('RECEIVE_PROTECTED_BRANCHES');
export const UPDATE_SELECTED_TYPE = ns('UPDATE_SELECTED_TYPE');
export const RECEIVE_HTTPS_ACCOUNT = ns('RECEIVE_HTTPS_ACCOUNT');
export const CREATE_FILE = ns('CREATE_FILE');
export const CHANGE_BLOB_SIZE = ns('CHANGE_BLOB_SIZE');
export const RECEIVE_BATCH_DATA_PROMISE = ns('RECEIVE_BATCH_DATA_PROMISE');
export const RECEIVE_BATCH_DATA_PROMISE_LOADING = ns('RECEIVE_BATCH_DATA_PROMISE_LOADING');

const { pathResource, resourceSubject, organization } = window.FORCE;

export function updateData(data) {
  return (dispatch) => {
    dispatch({
      type: UPDATE_DATA,
      data,
    });
  };
}

export function resetData() {
  return (dispatch, getState) => {
    const { pageInfo } = getState().root;
    dispatch({
      type: UPDATE_PAGE_INFO,
      data: pageInfo,
    });
  };
}

// 在projectFile内路由改变时，接收路由层发出的通知更新 selectedType 和 resourcePath
export function updateSetSelectedType(pageInfo) {
  return (dispatch) => {
    dispatch({
      type: UPDATE_SELECTED_TYPE,
      data: {
        selectedType: pageInfo.resourceSubject.subject,
        resourcePath: pageInfo.resourceSubject.path,
        selectedKeys: [pageInfo.resourceSubject.path],
      },
    });
  };
}

// 获取库的几个统计信息
export function getStatistic() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'projects.statistic',
        params: { projectId: pathResource.id },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_STATISTIC,
          data: result,
        });
      });
  };
}

// 获取保护分支信息
export function getProtectedBranchInfo(branchName) {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'projects.branches.protected',
        params: {
          projectId: pathResource.id,
          branch: utils.revisionEncodeURI(branchName),
        },
      })
      .then((result) => {
        let data = result;
        if (JSON.stringify(result) === '{}') {
          data = null;
        }
        dispatch({
          type: RECEIVE_PROTECTED_BRANCHES,
          data,
        });
      });
  };
}

// 收藏
export function doStar() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'projects.star',
        params: { projectId: pathResource.id },
      })
      .then(() => {
        dispatch(getStatistic());
      });
  };
}

// 取消收藏
export function doUnStar() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'projects.unstar',
        params: { projectId: pathResource.id },
      })
      .then(() => {
        dispatch(getStatistic());
      });
  };
}

export function removeProject() {
  return (dispatch, getState) => {
    const { isRemovingProject } = getState().project.projectFiles;
    if (isRemovingProject) {
      return;
    }
    updateData({
      isRemovingProject: true,
    })(dispatch);
    exceed
      .fetch({
        api: 'project.delete',
        params: { id: pathResource.id },
      })
      .then(() => {
        updateData({
          isRemovingProject: false,
        })(dispatch);
        Message.success({
          title: intl.get({
            id: 'code-assets.projectFiles.actions.Deleted',
            defaultMessage: '删除成功',
          }),
        });

        navigate('/');
      })
      .fail(() => {
        updateData({
          isRemovingProject: false,
        })(dispatch);
      });
  };
}

// 某个目录点击展开时，获取该目录的树结构
// 左侧树点击时，获取树
export function getExpandedTreeData(path, resolve) {
  return (dispatch, getState) => {
    const state = getState().project.projectFiles;
    const { allTreeData, treeData } = state;

    const treePromise = allTreeData
      ? new Promise((resolveFn) => {
          const children = getTreeChildren(allTreeData, path);
          resolveFn({
            list: children.map((item) => {
              return {
                ...item,
                path: item.id,
              };
            }),
          });
        })
      : exceed.forceFetch({
          api: 'projects.tree',
          params: { projectId: pathResource.id },
          data: {
            type: 'FLATTEN', // 取多层直到该层目录有多个文件或目录
            path,
            ref_name:
              resourceSubject.revisionType === 'branch'
                ? `refs/heads/${resourceSubject.revision}`
                : resourceSubject.revision,
          },
        });

    treePromise.then((result) => {
      if (!(result.list && result.list.length)) {
        resolve && resolve();
        return false;
      }

      function treeFunc(tree) {
        tree.forEach((item) => {
          if (item.id === path) {
            item.children = allTreeData
              ? result.list.map((itemDetail) => itemDetail.label)
              : result.list.map((pathTreeItem) => ({
                  id: `${path}/${pathTreeItem.name}`,
                  title: pathTreeItem.name,
                  name: pathTreeItem.name,
                  type: pathTreeItem.type,
                }));
          } else if (item.children) {
            treeFunc(item.children);
          }
        });
        return tree;
      }

      function dispatchResultFunc() {
        dispatch({
          type: RECEIVE_TREEDATA,
          data: treeFunc(treeData),
        });

        resolve && resolve();
      }

      const listData = allTreeData
        ? result.list.map((itemDetail) => itemDetail.label)
        : result.list;

      // 如果有 commit 类型数据，且没有请求过 submodules，则请求 submodules 后再渲染树
      if (!state.submodules && result.list.find((item) => item.type === 'commit')) {
        dispatch(
          getSubmodules(() => {
            dispatchResultFunc();
            // 每次加载数据，右侧更新表格
            dispatch(getRightTreeData(path || '', listData));
          }),
        );
      } else {
        dispatchResultFunc();
        setTimeout(() => {
          dispatch(getRightTreeData(path || '', listData));
        });
      }
      // 选中节点展开
      dispatch(modifyTreeSelectedKeys([path]));
    });
  };
}

// 获取所有的 submodule，根据 path 匹配文件
export function getSubmodules(cb) {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'projects.submodule',
        params: {
          projectId: pathResource.id,
          sha: utils.revisionEncodeURI(
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
          ),
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_SUBMODULES,
          data: result.list,
        });

        cb && cb();
      });
  };
}

// 获取所有文件
export function getAllFiles() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'projects.tree',
        params: { projectId: pathResource.id },
        data: {
          type: 'RECURSIVE', // 取到所有文件
          path: '',
          ref_name:
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
        },
      })
      .then((result) => {
        const { list } = result;
        if (list.length > 1000) {
          return;
        }
        const treeData = treeFromPaths(
          list.map((item) => item.path),
          '',
          (parent, file, explicit) => {
            const isBlob = explicit;
            let type = isBlob ? 'blob' : 'tree';
            const id = isBlob ? `${parent}${file}` : `${parent}${file}`.slice(0, -1);
            let newId = id;
            let is_lfs = false;
            list.forEach((listItem) => {
              if (listItem.path === id) {
                is_lfs = listItem.is_lfs;
                if (listItem.type === 'commit') {
                  newId = listItem.id;
                  type = 'commit';
                }
              }
            });
            return {
              id: newId,
              title: isBlob ? `${file}` : `${file}`.slice(0, -1),
              name: isBlob ? `${file}` : `${file}`.slice(0, -1),
              type,
              is_lfs,
              path: id,
            };
          },
          {},
          'children',
        );

        dispatch(
          updateData({
            allTreeData: treeData.children,
            allTreeFiles: list,
          }),
        );
      });
  };
}

// 从树结构中找到对应children
function getTreeChildren(tree, path) {
  let arr = [];
  const fn = (curTree) => {
    curTree.forEach((item) => {
      if (item.label && item.label.id === path) {
        arr = item.children || [];
      } else {
        item.children && fn(item.children);
      }
    });
  };

  fn(tree);
  return arr;
}

// 获取初始化的树结构
export function getInitTreeData(path, cb) {
  return (dispatch, getState) => {
    const pathSplitArr = path.split('/');
    const pathArr = pathSplitArr.map((item, i) => {
      let pathResult = '';
      for (let j = 0; j <= i; j++) {
        pathResult += `${j !== 0 ? '/' : ''}${pathSplitArr[j]}`;
      }
      return pathResult;
    });

    updateData({
      isInittingLeftTree: true,
    })(dispatch);

    // 插入根路径
    !(pathArr.length === 1 && pathArr[0] === '') && pathArr.unshift('');

    Promise.all(
      pathArr.map((item) =>
        exceed.forceFetch({
          api: 'projects.tree',
          params: { projectId: pathResource.id },
          data: {
            type: 'FLATTEN', // 取多层直到该层目录有多个文件或目录
            path: item,
            ref_name:
              resourceSubject.revisionType === 'branch'
                ? `refs/heads/${resourceSubject.revision}`
                : resourceSubject.revision,
          },
        })),
    )
      .then((result) => {
        const treeData = result;

        const state = getState().project.projectFiles;
        const expandedKeys = state.defaultExpandedKeys;
        let { selectedKeys } = state;
        const { resourcePath } = state;
        const resourcePathArr = resourcePath.split('/');

        function treeFunc(i) {
          if (!treeData[i]) {
            return false;
          }

          return treeData[i].list.map((treeItem) => {
            const nowPath = resourcePathArr[i];

            // 拿资源的绝对路径当id
            let absolutePath = '';
            for (let j = 0; j < i; j++) {
              absolutePath += `${j !== 0 ? '/' : ''}${resourcePathArr[j]}`;
            }
            const treeItemId = `${absolutePath}${absolutePath ? '/' : ''}${treeItem.name}`;

            if (treeItemId === resourcePath) {
              selectedKeys = [treeItemId];
            }

            // 正常目录的情况
            if (treeItem.type === 'tree' && treeItem.name === nowPath) {
              expandedKeys.push(treeItemId);

              return {
                id: treeItemId,
                title: treeItem.name,
                name: treeItem.name,
                type: treeItem.type,
                children: treeFunc(i + 1),
              };
            }

            // 多级折叠目录的情况（tree 接口 FLATTEN 模式目录会折叠）
            if (
              treeItem.type === 'tree' &&
              treeItem.name.indexOf(`${nowPath}/`) === 0 &&
              treeData[i + treeItem.name.split('/').length]
            ) {
              expandedKeys.push(treeItemId);

              return {
                id: treeItemId,
                title: treeItem.name,
                name: treeItem.name,
                type: treeItem.type,
                children: treeFunc(i + treeItem.name.split('/').length), // 跳过递归被折叠的目录
              };
            }

            // 文件的情况
            return {
              id: treeItemId,
              title: treeItem.name,
              name: treeItem.name,
              type: treeItem.type,
            };
          });
        }

        function dispatchResultFunc() {
          dispatch({
            type: RECEIVE_DEFAULTEXPANDEDKEYS,
            data: expandedKeys,
          });

          dispatch(modifyTreeSelectedKeys(selectedKeys));
          dispatch({
            type: RECEIVE_TREEDATA,
            data,
          });

          cb && cb();
        }

        const data = treeFunc(0);

        // 如果有 commit 类型数据，且没有请求过 submodules，则请求 submodules 后再渲染树
        let hasSubmodules = false;
        result.forEach((item) => {
          if (item.list.find((resource) => resource.type === 'commit')) {
            hasSubmodules = true;
          }
        });
        if (!state.submodules && hasSubmodules) {
          dispatch(
            getSubmodules(() => {
              dispatchResultFunc();
            }),
          );
        } else {
          dispatchResultFunc();
        }
      })
      .catch(() => {
        updateData({
          isInittingLeftTree: false,
          isInitedLeftTree: true,
        })(dispatch);
      });
  };
}

// 修改树选中的key
export function modifyTreeSelectedKeys(selectedKeys) {
  return {
    type: RECEIVE_SELECTEDKEYS,
    data: selectedKeys,
  };
}

/**
 * 右侧为树时，获取树
 * @param {*} path 路径
 * @param {*} data 展开树时，不需要发送请求，直接使用data数据作为右侧数据
 */
export function getRightTreeData(path, data) {
  return (dispatch, getState) => {
    const { submodules, isAtOverviewPage, selectedType, treeData } =
      getState().project.projectFiles;
    // 获取最近一次commit
    // blob类型不用请求树
    if (selectedType === 'blob') {
      return;
    }
    dispatch(getLastCommit());
    // 首页不是选择文件夹时不需要触发请求
    if (isAtOverviewPage && selectedType === '') {
      dispatch({
        type: RECEIVE_CURRENTTREEDATA,
        data: treeData,
      });

      return false;
    }

    updateData({
      isLoadingTable: true,
    })(dispatch);
    const promise = data
      ? new Promise((resolve) => {
          resolve({
            list: data,
          });
        })
      : exceed.forceFetch({
          api: 'projects.tree',
          params: { projectId: pathResource.id },
          data: {
            // DIRECT RECURSIVE FLATTEN 这3个值，分别代表只取1层，循环取所有文件，取多层直到该层目录有多个文件或目录
            type: 'FLATTEN',
            path,
            ref_name:
              resourceSubject.revisionType === 'branch'
                ? `refs/heads/${resourceSubject.revision}`
                : resourceSubject.revision,
          },
        });

    promise.then((result) => {
      const { list } = result;
      const dispatchResultFunc = () => {
        dispatch({
          type: RECEIVE_CURRENTTREEDATA,
          data: list,
        });

        dispatch(getPathLastCommit(path, list));
      };

      // 如果有 commit 类型数据，且没有请求过 submodules，则请求 submodules 后再渲染树
      if (!submodules && list.find((item) => item.type === 'commit')) {
        dispatch(
          getSubmodules(() => {
            dispatchResultFunc();
          }),
        );
      } else {
        dispatchResultFunc();
      }
    });
  };
}

// 加载表格时获取commit数据

export function changeRouter(data) {
  return {
    type: CHANGE_ROUTER,
    data,
  };
}

// 获取文件内容
// 接口见：http://gitlab.alibaba-inc.com/help/api/repositories.md#raw-file-content
export function getBlobs(path) {
  return (dispatch, getState) => {
    const { resourcePath } = getState().project.projectFiles;
    if (!pathResource.id) {
      return;
    }
    updateData({
      isGettingBlob: true,
    })(dispatch);
    exceed
      .forceFetch({
        api: 'projects.blobs',
        params: { projectId: pathResource.id },
        data: {
          filepath: path || resourcePath,
          ref:
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_BLOB,
          data: result,
        });

        updateData({
          isGettingBlob: false,
        })(dispatch);
      });
  };
}

export function getServiceSettings(cb) {
  return () => {
    getProjectServices()
      .then(() => {
        cb && cb();
      })
      .catch(() => {
        cb && cb();
      });
  };
}

// 获取文件类型及内容
export function get_general_info_and_blobs(path) {
  return (dispatch, getState) => {
    const { resourcePath } = getState().project.projectFiles;
    if (!pathResource.id) {
      return;
    }
    const file_path = path || resourcePath;
    updateData({
      isGettingBlob: true,
      isFileNotFound: false,
      fileReqFailInfo: '',
    })(dispatch);
    exceed
      .fetch({
        api: 'projects.general_info_and_blobs',
        params: {
          projectId: pathResource.id,
          ref: encodeURIComponent(
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
          ),
        },
        data: {
          file_path,
          max_blob_size: '',
        },
      })
      .then((result) => {
        dispatch(
          updateData({
            renderType: result.type,
            blobSize: result.size,
            is_lfs: result.is_lfs,
            lfs_oid: result.lfs_oid || '',
            blob: result.content || '',
            isGettingBlob: false,
          }),
        );
      })
      .fail((response) => {
        updateData({
          isGettingBlob: false,
        })(dispatch);
        try {
          const responseText = JSON.parse(response.responseText);
          if (responseText.errorCode === 'LFS_OBJ_NOT_FOUND_ERROR') {
            updateData({
              isFileNotFound: true,
              is_lfs: true,
              isGettingBlob: false,
              blob: '',
            })(dispatch);
          } else {
            updateData({
              isFileNotFound: false,
              is_lfs: false,
              isGettingBlob: false,
              fileReqFailInfo: responseText.message || responseText.errorCode,
              blob: '',
            })(dispatch);
          }
        } catch (e) {
          Message.error({
            title: intl.get({
              id: 'code-assets.projectFiles.actions.TheSystemIsBusyPlease',
              defaultMessage: '系统繁忙，请稍后重试',
            }),
          });
        }
      });
  };
}

// DESPTERED 从dom中获取文件内容
export function getBlobsFromDom() {
  return (dispatch) => {
    dispatch({
      type: RECEIVE_BLOB,
      data: {
        content: document.getElementById('J_blob_content').innerHTML,
        size: document.getElementById('J_blob_content_size').innerHTML,
      },
    });
  };
}

// 获取文件内容(base64编码，图片和二进制文件下载时用)
// 接口见：http://gitlab.alibaba-inc.com/help/api/repositories.md#raw-file-content
export function getBlobsBase64(path) {
  return (dispatch, getState) => {
    const { resourcePath } = getState().project.projectFiles;
    exceed
      .forceFetch({
        api: 'projects.blobsBase64',
        params: { projectId: pathResource.id },
        data: {
          file_path: path || resourcePath,
          ref:
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_BLOB,
          data: result,
        });
      });
  };
}

// 新增获取文件内容以及最新的提交信息
export function getBlobAndCommitWithPath() {
  return (dispatch, getState) => {
    const { resourcePath } = getState().project.projectFiles;
    dispatch(get_general_info_and_blobs(resourcePath));
    dispatch(getLastCommit());
  };
}

// 获取分支文件最近提交接口
// 请求参数：
// sha - 分支名或版本号
// filepath - 文件相对路径
export function getLastCommit() {
  return (dispatch, getState) => {
    const { resourcePath } = getState().project.projectFiles;
    const sha =
      resourceSubject.revisionType === 'branch'
        ? `refs/heads/${resourceSubject.revision}`
        : resourceSubject.revision;
    if (!pathResource.id || !sha) {
      return;
    }
    updateData({
      isLoadingLastCommit: true,
    })(dispatch);
    exceed
      .forceFetch({
        api: 'projects.files.last_commit',
        params: { projectId: pathResource.id },
        data: {
          sha,
          filepath: resourcePath,
          show_signature: true,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_LASTCOMMIT,
          data: result,
        });

        updateData({
          isLoadingLastCommit: false,
        })(dispatch);
      });
  };
}

export function getBatchDataOnScroll(num) {
  return (dispatch, getState) => {
    const { batchDataConfig, batchDataLoading } = getState().project.projectFiles;
    const { allPromises, i, total } = batchDataConfig;
    if (!allPromises || batchDataLoading) return;
    if (i * 30 < num) {
      dispatch({
        type: RECEIVE_BATCH_DATA_PROMISE_LOADING,
        data: true,
      });

      getBatchData(dispatch, allPromises, i + 1, total, num);
    }
  };
}

function getBatchData(dispatch, allPromises, i, total, num) {
  if (i === allPromises.length) {
    dispatch({
      type: RECEIVE_BATCH_DATA_PROMISE_LOADING,
      data: false,
    });

    return;
  }
  lastCommitPromise(allPromises[i]).then((result) => {
    const data = [...total, ...result];
    dispatch({
      type: RECEIVE_PATHLASTCOMMIT_BATCH,
      data,
    });

    dispatch({
      type: RECEIVE_BATCH_DATA_PROMISE,
      data: {
        allPromises,
        i,
        total: data,
      },
    });

    if (num !== undefined && i * 30 < num) {
      getBatchData(dispatch, allPromises, i + 1, data, num);
    } else {
      dispatch({
        type: RECEIVE_BATCH_DATA_PROMISE_LOADING,
        data: false,
      });
    }
    // getBatchData(dispatch, allPromises, i + 1, data);
  });
}

// 获取分支文件最近提交接口
// 请求参数：
// sha - 分支名或版本号
// filepath - 文件相对路径
export function getPathLastCommit(path, files) {
  return (dispatch) => {
    const list_of_files = [];
    let batch_size;
    const filesLength = files.length;
    if (!filesLength) {
      return;
    }

    // 批量查询，每批次的个数
    const perBatchSize = 30;

    if (filesLength > perBatchSize) {
      // 大于50分批次查询
      batch_size = Math.ceil(filesLength / perBatchSize);
      for (let i = 0; i < batch_size; i++) {
        list_of_files[i] = files.slice(
          perBatchSize * i,
          Math.min(perBatchSize * (i + 1), filesLength),
        );
      }

      const allPromises = [];

      for (let i = 0; i < batch_size; i++) {
        const batchFiles = list_of_files[i];
        const batchFilesPath = [];
        for (let j = 0; j < batchFiles.length; j++) {
          batchFilesPath[j] = batchFiles[j].path;
        }
        allPromises.push({ path: batchFilesPath });
      }

      getBatchData(dispatch, allPromises, 0, []);
    } else {
      const batchFilesPath = [];
      for (let j = 0; j < files.length; j++) {
        batchFilesPath[j] = files[j].path;
      }
      lastCommitPromise({ path: batchFilesPath })
        .then((result) => {
          dispatch({
            type: RECEIVE_PATHLASTCOMMIT_BATCH,
            data: result,
          });
        })
        .catch((err) => {
          console.error(err);
        });
    }
  };
}

function lastCommitPromise(data) {
  return new Promise((resolve, reject) => {
    exceed
      .fetch({
        api: 'projects.files.last_commit_batch',
        params: {
          projectId: pathResource.id,
          sha: utils.revisionEncodeURI(
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
          ),
        },

        data,
      })
      .then((result) => {
        const list = result.slice(1);
        resolve(list);
      })
      .fail((err) => {
        reject(err);
      });
  });
}

// 通过邮箱拿用户信息
export function getByEmail(email) {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'users.getByEmail',
        data: {
          email,
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_LASTCOMMIT_USER,
          data: result,
        });
      });
  };
}

// 删除文件：注意这个delete接口参数需要带在query里
// 接口见：http://gitlab.alibaba-inc.com/help/api/repository_files.md
export function deleteFile(formData, commit_message, cb) {
  return (dispatch, getState) => {
    const { resourcePath } = getState().project.projectFiles;
    const { branch_name, task_ids } = formData;
    exceed
      .fetch({
        api: 'projects.files.delete.associateTask',
        params: {
          task_ids,
          project_id: pathResource.id,
          file_path: utils.revisionEncodeURI(resourcePath),
          commit_message: utils.revisionEncodeURI(commit_message), // 因为commit_message要带在query里，所以也做EncodeURI
          branch_name: utils.revisionEncodeURI(branch_name),
        },
      })
      .then(() => {
        cb && cb(true);
      })
      .fail(() => {
        cb && cb(false);
      });
  };
}

// 新建文件
// 接口见：http://gitlab.alibaba-inc.com/help/api/repository_files.md
export function createFile(formData, commit_message, cbSucc, cbErr) {
  return (dispatch) => {
    const { branch_name, file_path, content, task_ids } = formData;

    exceed
      .fetch({
        api: 'projects.files.new.associateTask',
        data: {
          project_id: pathResource.id,
          task_ids,
          file_path,
          commit_message,
          branch_name,
          encoding: 'base64',
          content,
        },
      })
      .then(() => {
        dispatch({
          type: CREATE_FILE,
          data: true,
        });

        cbSucc && cbSucc();
      })
      .fail(() => {
        cbErr && cbErr();
      });
  };
}

// 新建目录
export function createDir(formData, cb) {
  return () => {
    const { commit_message, branch_name, file_path } = formData;

    exceed
      .forceFetch({
        api: 'projects.dirs.new',
        params: {
          projectId: pathResource.id,
        },

        data: {
          file_path,
          commit_message,
          branch_name,
        },
      })
      .then(() => {
        cb && cb();
      });
  };
}

// 导入指定行的代码
export function addSnippet(data) {
  return {
    type: ADD_SNIPPET,
    data,
  };
}

// 清空指定片段的代码
export function clearSnippet(data) {
  return {
    type: CLEAR_SNIPPET,
    data,
  };
}

// 更新待消费的跳转行号
export function updateJumpLineCode(jump_line_code) {
  return (dispatch) => {
    dispatch({
      type: RECEIVE_JUMP_LINE_CODE,
      data: jump_line_code,
    });
  };
}

// 停止导入
export function stopImportProject() {
  return (dispatch, getState) => {
    const { root, projectFiles } = getState().project;
    const { projectInfo } = root;
    const { isStoppingImport } = projectFiles;
    const { id } = projectInfo;
    if (isStoppingImport) {
      return;
    }
    updateData({
      isStoppingImport: true,
    })(dispatch);
    exceed
      .fetch({
        api: 'projects.single.import.stop',
        params: {
          id,
        },
      })
      .then((result) => {
        if (result.result) {
          dispatch(getProjectInfo());
        } else {
          updateData({
            isStoppingImport: false,
          })(dispatch);
          Message.error({
            title: intl.get({
              id: 'code-assets.projectFiles.actions.FailedToTerminateTheImport',
              defaultMessage: '终止导入失败',
            }),
          });
        }
      })
      .fail((err) => {
        updateData({
          isStoppingImport: false,
        })(dispatch);
        console.error(err);
      });
  };
}
// 初始化空库
export function initEmptyProject() {
  return (dispatch, getState) => {
    const { root, projectFiles } = getState().project;
    const { projectInfo } = root;
    const { isInittingImport } = projectFiles;
    const { id } = projectInfo;
    if (isInittingImport) {
      return;
    }
    updateData({
      isInittingImport: true,
    })(dispatch);
    exceed
      .fetch({
        api: 'projects.single.init',
        params: { id },
      })
      .then((result) => {
        if (result.result) {
          // 获取到最新库接口信息后，标记初始化完成，防止有重复触发的机会
          dispatch(
            getProjectInfo(() => {
              updateData({
                isInittingImport: false,
              })(dispatch);
            }),
          );
        } else {
          Message.error({
            title: intl.get({
              id: 'code-assets.projectFiles.actions.InitializationFailed',
              defaultMessage: '初始化失败',
            }),
          });

          updateData({
            isInittingImport: false,
          })(dispatch);
        }
      })
      .fail((err) => {
        updateData({
          isInittingImport: false,
        })(dispatch);
        console.error(err);
      });
  };
}

export function getHttpsAccount() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'user.https.account',
        data: {
          x_code_timestamp: new Date().getTime(),
        },
      })
      .then((result) => {
        dispatch({
          type: RECEIVE_HTTPS_ACCOUNT,
          data: result,
        });
      });
  };
}

export function getIpWhiteList() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'organization.ip_setting',
        params: {
          id: organization.id,
        },
      })
      .then((result) => {
        updateData({
          ipSetting: result,
        })(dispatch);
      });
  };
}

export function getCloneDownloadSetting() {
  return (dispatch) => {
    exceed
      .forceFetch({
        api: 'project.clone_download',
        params: {
          projectId: pathResource.id,
        },
      })
      .then((result) => {
        updateData({
          project_clone_download: result,
        })(dispatch);
      });
  };
}
